//===============================================================================
// Microsoft patterns & practices
// Guidance Explorer Offline Client
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================

using System;
using System.Windows.Forms;
using GuidanceExplorer.Model;
using GuidanceExplorer.Model.Conditions;

namespace GuidanceExplorer.Controls
{
    /// <summary>
    /// Represents a folder in the tree view.
    /// </summary>
    [MenuItemAttribute(500, "context\\New Folder", GuidanceExplorer.Commands.NewFolder, typeof(ModelItemMenuItemIsEditableCondition), Keys.None)]
	[MenuItemAttribute(510, "context\\New Checklist", GuidanceExplorer.Commands.NewChecklist, typeof(MenuItemUnderSolutionNodeCondition), Keys.None)]
    [MenuItemAttribute(520, "context\\New View", GuidanceExplorer.Commands.NewView, typeof(ModelItemMenuItemIsEditableCondition), Keys.None)]
   // [MenuItemAttribute(530, "context\\New Search View", GuidanceExplorer.Commands.NewSearchView, typeof(ModelItemMenuItemIsEditableCondition), Keys.None)]
    [MenuItemAttribute(540, "context\\-", null, typeof(OrGenericMenuItemCondition<ModelItemMenuItemIsEditableCondition, MenuItemUnderSolutionNodeCondition>), Keys.None)]
    //[MenuItemAttribute(550, "context\\Add To View...", GuidanceExplorer.Commands.MoveGuidanceItemToView, typeof(NotGenericMenuItemCondition<MenuItemUnderSolutionNodeCondition>), Keys.None)]
	[MenuItemAttribute(560, "context\\Export as Library...", GuidanceExplorer.Commands.ExportFolderAsLibrary, typeof(NotGenericMenuItemCondition<MenuItemUnderSolutionNodeCondition>), Keys.None)]
    [MenuItemAttribute(565, "context\\Export Folder...", GuidanceExplorer.Commands.ExportSolutionModelItem, typeof(MenuItemUnderSolutionNodeCondition), Keys.None)]
    [MenuItemAttribute(567, "context\\Import to Folder...", GuidanceExplorer.Commands.ImportSolutionItemToFolder, typeof(MenuItemUnderSolutionNodeCondition), Keys.None)]
    //[MenuItemAttribute(561, "context\\Save Folder as...", GuidanceExplorer.Commands.SaveFolderAs, Keys.None)]
    [MenuItemAttribute(570, "context\\-", null, typeof(OrGenericMenuItemCondition<ModelItemMenuItemIsEditableCondition, MenuItemUnderSolutionNodeCondition>),Keys.None)]
    [MenuItemAttribute(580, "context\\Delete Folder", GuidanceExplorer.Commands.DeleteFolder, typeof(ModelItemMenuItemIsEditableCondition), Keys.None)]
    [MenuItemAttribute(590, "context\\Rename Folder", GuidanceExplorer.Commands.RenameFolder, typeof(ModelItemMenuItemIsEditableCondition), Keys.None)]
    public class FolderNode : ModelNode<Folder>
    {
        /// <summary>
        /// Factory.
        /// </summary>
        /// <returns></returns>
        public static FolderNode New()
        {
            return new FolderNode();
        }

        /// <summary>
        /// Private default constructor.
        /// </summary>
        private FolderNode() : base("a folder", 10, 10) { }

        protected FolderNode(string text, int imageIndex, int selectedImageIndex) : base (text,imageIndex,selectedImageIndex){ } 

        public override bool CanDrop(IModelItem modelNode)
        {
            Library thisLibrary = ModelInstance.GetContainerLibrary();
			
			ViewNode viewNode = modelNode as ViewNode;
            FolderNode folderNode = modelNode as FolderNode;
            SearchViewNode searchViewNode = modelNode as SearchViewNode;
			ChecklistNode checkListNode = modelNode as ChecklistNode;
			MenuItemUnderSolutionNodeCondition IsUnderSolutionNode = new MenuItemUnderSolutionNodeCondition();

            GuidanceExplorer.Model.View view = null;
            if (checkListNode != null)
            {
                view = checkListNode.ModelInstance;

				if (IsUnderSolutionNode.ShowMenuItem(null, checkListNode) && IsUnderMyViews(this))
				{
					return false;
				}
            }
            else if (viewNode != null)
            {
                view = viewNode.ModelInstance;

				if (IsUnderSolutionNode.ShowMenuItem(null, viewNode) && IsUnderMyViews(this))
				{
					return false;
				}
				if (IsUnderSolutionNode.ShowMenuItem(null, this) && (viewNode.IsUnderMyViews(viewNode) || viewNode.IsUnderLibrary(viewNode)))
				{
					return false;
				}
            }
            if (view != null)
            {
                /*
                 * Test for views:
                 *  Only views of the same library can be drop in the library.
                 *  Views can't be droped in its parent folder.
                 */
                Library otherLibrary = view.GetContainerLibrary();

                //Root views cant be dragged
                if (view.RootView)
                {
                    return false;
                }

                //If different library return false
                if (!Object.ReferenceEquals(otherLibrary, thisLibrary) && ( thisLibrary != null ))
                {
                    return false;
                }

                //Can't drag to its parent.
                if (Object.ReferenceEquals(view.ParentFolder, ModelInstance))
                {
                    return false;
                }

                return true;
            }
            else if (folderNode != null)
            {
				
                /*
                 * Test for folders:
                 *  Only folders of the same library can be drop in the library.
                 *  Folders can't be droped in its parent folder.
                 *  A folder can't be droped to any of its childs.
                 */
				
                Library otherLibrary = folderNode.ModelInstance.GetContainerLibrary();

				if ( thisLibrary != null )
				{
					if (thisLibrary.ReadProtection == ReadProtection.ReadOnly) return false;
				}

                //If different library return false
				if ((otherLibrary != null) && (thisLibrary != null) && !Object.ReferenceEquals(otherLibrary, thisLibrary))
                {
                    return false;
                }

                //Can't drag to its parent.
                if (Object.ReferenceEquals(folderNode.ModelInstance.ParentFolder, ModelInstance))
                {
                    return false;
                }

                //Find the node in its childs.
                if (FindNodeInChilds(folderNode, this))
                {
                    return false;
                }

				if (IsUnderMyViews(this) && IsUnderSolutionNode.ShowMenuItem(null,folderNode))
				{
					return false;
				}

				if (IsUnderSolutionNode.ShowMenuItem(null, this) && !IsUnderSolutionNode.ShowMenuItem(null, folderNode))
				{
					return false;
				}

                return true;
            }
            else if (searchViewNode != null)
            {
                //Root views cant be dragged
                if (searchViewNode.ModelInstance.RootView)
                {
                    return false;
                }

                return true;
            }
            return false;
        }

        /// <summary>
        /// Whether the node is editable.
        /// </summary>
        public override bool IsEditable
        {
            get
            {
                Library library = ModelInstance.GetContainerLibrary();
                if (library != null)
                {
                    return (library.ReadProtection == ReadProtection.ReadWrite);
                }
                return true;
            }
        }

		/// <summary>
		/// Clone a folder.
		/// </summary>
		public FolderNode Clone(Folder newModelInstance)
		{
			FolderNode cloneNode = new FolderNode();
			cloneNode.Text = Text;
			cloneNode.SelectedItem = SelectedItem;
			if (newModelInstance == null)
			{
				cloneNode.ModelInstance = (Folder)ModelInstance.Clone();
			}
			else
			{
				cloneNode.ModelInstance = newModelInstance;
			}

			if (Nodes.Count > 0)
			{
				foreach (TreeNode tempNode in Nodes)
				{
					FolderNode tempFolderNode = tempNode as FolderNode;
					ViewNode tempViewNode = tempNode as ViewNode;
					SearchViewNode tempSearchViewNode = tempNode as SearchViewNode;
					TreeNode copyNode = null;

					if (tempFolderNode != null)
					{
						Folder folder = tempFolderNode.ModelInstance.Clone();
						folder.ParentFolder = cloneNode.ModelInstance;
						copyNode = (TreeNode)tempFolderNode.Clone(folder);
					}
					else if (tempViewNode != null)
					{
						GuidanceExplorer.Model.View view = tempViewNode.ModelInstance.Clone();
						view.ParentFolder = cloneNode.ModelInstance;
						view.Container = null;
						copyNode = (TreeNode)tempViewNode.Clone(view);
					}
					else if (tempSearchViewNode != null)
					{
						SearchView searchView = (SearchView)tempSearchViewNode.ModelInstance.Clone();
						searchView.ParentFolder = cloneNode.ModelInstance;
						searchView.ReadedScope = SearchViewScope.Folder;
						searchView.Container = null;
						copyNode = (TreeNode)tempSearchViewNode.Clone(searchView);
					}

					cloneNode.Nodes.Add(copyNode);
				}
			}

			return cloneNode;
		}

		/// <summary>
		///  
		/// </summary>
		/// <param name="viewNode"></param>
		/// <returns></returns>
		private bool IsUnderMyViews(FolderNode folderNode)
		{
			if (folderNode.ModelInstance.ParentFolder != null)
			{
				Folder folder = folderNode.ModelInstance.ParentFolder;
				while (folder != null)
				{
					if ((folder.Container != null) && (folder.Container.GetType() == typeof(UserViews)))
					{
						return true;
					}
					folder = folder.ParentFolder;
				}
				return false;

			}
			else if (folderNode.ModelInstance.Container.GetType() == typeof(UserViews))
			{
				return true;
			}
			else
			{
				return false;
			}

		}
		private bool IsUnderLibrary(FolderNode folderNode)
		{
			if (folderNode.ModelInstance.ParentFolder != null)
			{
				Folder folder = folderNode.ModelInstance.ParentFolder;
				while (folder != null)
				{
					if ((folder.Container != null) && (folder.Container.GetType() == typeof(Library)))
					{
						return true;
					}
					folder = folder.ParentFolder;
				}
				return false;

			}
			else if (folderNode.ModelInstance.Container.GetType() == typeof(Library))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
    }
}

